<<<<<<< HEAD

=======
>>>>>>> 3210d9b9a99c117811f1b83a2fa3dff1321ac49c
import java.util.AbstractSet;
import java.util.Iterator;
import java.util.NoSuchElementException;

public class ClosedHashSet extends AbstractSet<Integer> {

	private int size = 0;
	private int capacity = 0;
	private Integer values[];
	private int flags[]; // 0  EMPTY, 1  DELETED, 2  USED

	public ClosedHashSet(int capacity) {
		if (capacity < 0)
			throw new IllegalArgumentException("Invalid argument");
		this.capacity = capacity;
		values = new Integer[capacity];
		flags = new int[capacity];
	}

	private int hashkey(int value) {
		return ((value >> 11) ^ value) % capacity;
	}

	public boolean add(Integer value) {
		if (size == capacity)
			throw new ArrayIndexOutOfBoundsException("Array is full");
		if (value == null)
			throw new IllegalArgumentException("Argument can't be null");
		int index = hashkey(value);
		while (flags[index] > 1) {
			index = (index + 1) % capacity;
		}
		values[index] = value;
		flags[index] = 2;
		size++;
		return true;
	}

	public boolean remove(int value) {
		int index = hashkey(value);
		int step = 0;
		while (true) {
			if (flags[index] == 0 || step == capacity)
				return false;
			if (flags[index] == 2 && values[index] == value) {
				flags[index] = 1;
				values[index] = null;
				size--;
				return true;
			}
			step++;
			index = (index + 1) % capacity;
		}
	}

	public boolean contains(int value) {
		int index = hashkey(value);
		int step = 0;
		while (true) {
			if (flags[index] == 0 || step == capacity)
				return false;
			if (flags[index] == 2 && values[index] == value) {
				return true;
			}
			index = (index + 1) % capacity;
			step++;
		}
	}

	class CHSIterator implements Iterator<Integer> {
		private int cur = 0;

		@Override
		public Integer next() {
			if (hasNext()) {
				for (int i = cur; i < capacity; i++) {
					if (values[cur] != null)
						break;
					cur = i;
				}
				return values[cur++];
			} else
				throw new NoSuchElementException();
		}

		@Override
		public boolean hasNext() {
			for (int i = cur; i < capacity; i++) {
				if (values[i] != null)
					return true;				
			}
			return false;
		}

		public CHSIterator(int pos) {
			cur = pos;
		}

		@Override
		public void remove() {
			throw new UnsupportedOperationException(
					"Operation is not supported");
		}
	}

	@Override
	public int size() {
		return this.size;
	}

	public void clear() {
		for (int i = 0; i < capacity; i++) {
			flags[i] = 0;
			values[i] = null;
		}
		size = 0;
	}

	@Override
	public CHSIterator iterator() {
		return new CHSIterator(0);
	}

	public static void main(String[] args) {
		System.out.println("Hello world!");

		try {

			ClosedHashSet a;
			a = new ClosedHashSet(55);
			System.out.println("Empty: " + a.isEmpty());

			System.out.println("Size: " + a.size());
			a.add(1);
			a.add(2);
			a.add(3);
			a.add(4);
			a.add(5);
			System.out.println("Contains 5: " + a.contains(5));
			System.out.println(a.toString());
			System.out.println("Contains 45: " + a.contains(45));
			System.out.println("Contains 0: " + a.contains(0));
			a.remove(5);
			System.out.println(a.toString());
			System.out.println("Contains 5: " + a.contains(5));
			System.out.println("Empty: " + a.isEmpty());
			System.out.println(a.toString());
			a.clear();
			System.out.println("Empty: " + a.isEmpty());
			System.out.println(a.toString());
		} catch (IllegalArgumentException | ArrayIndexOutOfBoundsException
				| UnsupportedOperationException e) {
			System.err.println(e.getMessage());
		}
	}
}